package com.jun.common.core.utils;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

/**
 * @author yuejun.li
 * @date 2024/10/19 18:18
 */
@Component
public class ApplicationUtil implements ApplicationContextAware, EnvironmentAware {

    private static ApplicationContext applicationContext;

    private static Environment environment;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationUtil.applicationContext = applicationContext;
    }

    @Override
    public void setEnvironment(Environment environment) {
        ApplicationUtil.environment = environment;
    }

    /**
     * 根据bean的类型从spring容器中获取bean实例
     * @param clazz bean的类型
     * @param <T>
     * @return 指定类型的bean实例
     */
    public static <T> T getBean(Class<T> clazz) {
        return applicationContext.getBean(clazz);
    }

    /**
     * 根据bean名称和bean的类型从spring容器中获取bean实例
     * @param name bean的名称
     * @param clazz bean的类型
     * @param <T>
     * @return 指定类型的bean实例
     */
    public static <T> T getBean(String name, Class<T> clazz) {
        return applicationContext.getBean(name, clazz);
    }

    /**
     * 根据bean的名称从spring容器中获取bean实例
     * @param beanName bean的名称
     * @return
     */
    public static Object getBean(String beanName) {
        return applicationContext.getBean(beanName);
    }

    /**
     * 判断spring容器中是否有指定bean名称的bean实例
     * @param name bean的名称
     * @return
     */
    public static boolean containsBean(String name) {
        return applicationContext.containsBean(name);
    }


    /**
     * 根据bean名称从spring容器中获取bean名称对应实例的类型
     * @param name bean的名称
     * @return
     * @throws NoSuchBeanDefinitionException
     */
    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
        return applicationContext.getType(name);
    }

    /**
     * 根据配置项key的名称获取对应的配置项的值
     * 比如application.properties配置文件中有 url=www.baidu.com的配置，
     * 则getProperty("url")的值就是www.baidu.com
     * @param key 配置项的名称，比如url
     * @return
     */
    public static String getProperty(String key){
        return environment.getProperty(key);
    }

    /**
     * 根据配置项key的名称获取配置项的值，并将值转换为指定的类型
     * 比如application.properties配置文件中有age=18的配置项
     * 因为age的值是个整数，所以我们可以直接通过本方法获取整数的age值
     * getProperty("age",Integer.class)的结果就是整数18
     * @param key 配置项的名称
     * @param targetType 配置项对应的值的类型
     * @param <T>
     * @return 指定类型的配置项的值
     */
    public static <T> T getProperty(String key,Class<T> targetType) {
        return environment.getProperty(key,targetType);
    }
}
